package util.biz.excel;


import util.util.DevComUtil;
import util.util.DevFileUtil;
import util.util.error.BizException;
import util.biz.excel.ExcelCheckConfig.RowData;
import util.biz.excel.ExcelConverConfig.ExcelCell;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @author: liW
 * @date: 2020/11/27 18:20
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ExcelReadConfig<T> {

  /**
   * sheet页面
   */
  private Sheet sheet;

  /**
   * 读取配置
   */
  private ExcelConverConfig<T> config;

  /**
   * 构造函数
   */
  private Supplier<T> supplier;

  /**
   * 开始行
   */
  private int startRowNo;

  /**
   * 结束行
   */
  private int endRowNo;

  /**
   * 若为空，则停止读取
   */
  private Function<T, ?> stopFunction;

  /**
   * 校验请求头是否是模板
   *
   * @param titleRowNo 标题所在行
   * @return converConfig 配置信息
   */
  public ExcelReadConfig<T> checkTitle(int titleRowNo) {
    try {

      List<ExcelCell> list = this.getConfig().getList();
      Sheet sheet = this.getSheet();
      Row row = sheet.getRow(titleRowNo);
      for (ExcelCell titleCell : list) {
        String title = row.getCell(titleCell.getCellNo()).getStringCellValue();
        if (!titleCell.getTitle().equals(title)) {
          throw new BizException("校验表头出错");
        }
      }
      return this;
    } catch (Exception e) {
      e.printStackTrace();
      throw new BizException("校验表头出错");
    }
  }


  /**
   * 读取sheet中的值，转换为实体集合
   *
   * @param <D> 从excel表中获取到的数据类型
   * @param <R> 实体需要的数据类型
   * @return 实体集合
   */
  public <D, R> List<RowData<T>> readSheet() {
    Sheet sheet = this.getSheet();
    int endRowNo = this.getEndRowNo();
    if (endRowNo == 0) {
      endRowNo = sheet.getLastRowNum();
    }
    // 第一行 序号
    int startRowNo = this.getStartRowNo();

    List<RowData<T>> list = new ArrayList<>(endRowNo - startRowNo);



    ExcelConverConfig<T> config = this.getConfig();
    Supplier<T> supplier = this.getSupplier();
    int n = 1;
    for (int i = startRowNo; i < endRowNo; i++) {
      Row row = sheet.getRow(i);
      List<ExcelCell> li = config.getList();
      T t = supplier.get();
      for (ExcelCell<T, D, R> cell : li) {
        Function<D, R> converFuntion = cell.getConverFunction();
        if (converFuntion != null) {
          R apply = converFuntion
              .apply(DevFileUtil.getCellValueObject(row, cell.getCellNo()));
          cell.getBiConsumer().accept(t, apply);
        } else {
          cell.getBiConsumer()
              .accept(t, DevFileUtil.getCellValueObject(row, cell.getCellNo()));
        }
      }
      Function<T, ?> stopFunction = this.getStopFunction();
      if (!DevComUtil.isEmpty(stopFunction) && DevComUtil.isEmpty(stopFunction.apply(t))) {
        break;
      }
      list.add(RowData.getInstance(n++, t));
    }
    return list;
  }


}
